package org.glandais.games.rebondrobots.board;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class Robots {

	private Cell[] positions = new Cell[4];

	public Cell getPosition(RobotColor color) {
		return positions[color.ordinal()];
	}

	public void setPosition(RobotColor color, Cell cell) {
		positions[color.ordinal()] = cell;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + Arrays.hashCode(positions);
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Robots other = (Robots) obj;
		if (!Arrays.equals(positions, other.positions))
			return false;
		return true;
	}

	public Robots move(Board board, RobotColor color, Direction direction) {
		Robots result = new Robots();

		for (int i = 0; i < positions.length; i++) {
			result.positions[i] = positions[i];
		}

		Cell cell = getPosition(color);

		int dx = 0;
		int dy = 0;
		switch (direction) {
		case EAST:
			dx = +1;
			dy = 0;
			break;
		case WEST:
			dx = -1;
			dy = 0;
			break;
		case NORTH:
			dx = 0;
			dy = -1;
			break;
		case SOUTH:
			dx = 0;
			dy = +1;
			break;
		default:
			break;
		}

		while (canContinue(direction, cell, dx, dy, board, color)) {
			cell = board.getCell(cell.getX() + dx, cell.getY() + dy);
		}
		result.setPosition(color, cell);

		return result;
	}

	private boolean canContinue(Direction direction, Cell cell, int dx, int dy,
			Board board, RobotColor color) {
		if (cell.getBorder(direction).isWall()) {
			return false;
		}
		// the next one is within the board, otherwise we had a wall
		Cell nextCell = board.getCell(cell.getX() + dx, cell.getY() + dy);
		RobotColor[] colors = RobotColor.values();
		for (RobotColor robotColor : colors) {
			if (robotColor != color) {
				if (nextCell.equals(getPosition(robotColor))) {
					return false;
				}
			}
		}
		return true;
	}

	public static Robots createRandomRobots(Board board, Random r) {
		Robots robots = new Robots();
		Set<Cell> cells = new HashSet<Cell>();
		RobotColor[] colors = RobotColor.values();
		for (RobotColor color : colors) {
			Cell cell = null;
			do {
				cell = board.getCell(r.nextInt(16), r.nextInt(16));
			} while (validCell(cells, cell));
			cells.add(cell);
			robots.setPosition(color, cell);
		}
		return robots;
	}

	private static boolean validCell(Set<Cell> cells, Cell cell) {
		if (cell.getX() >= 7 && cell.getX() <= 8 && cell.getY() >= 7
				&& cell.getY() <= 8) {
			return true;
		}
		return cells.contains(cell);
	}
}
